/*
 *
 * *******************************************************************
 *   @项目名称: BHex Android
 *   @文件名称: ImgPickHelper.java
 *   @Date: 11/29/18 3:21 PM
 *   @Author: chenjun
 *   @Copyright（C）: 2018 BlueHelix Inc.   All rights reserved.
 *   注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的.
 *  *******************************************************************
 *
 */

package io.bhex.baselib.utils.crop;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;

import io.bhex.baselib.utils.AsyncLoaderImage;
import io.bhex.baselib.utils.DebugLog;
import io.bhex.baselib.utils.ImageUtils;
import io.bhex.baselib.utils.PixelUtils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * 获取照片的帮助类，可用于头像设置等
 */
public class ImgPickHelper {

    private static final int REQUEST_Gallery = 126;

    private static final int REQUEST_CROP = 127;

    private static final int REQUEST_CAMERA = 128;

    private static final String CROP_CACHE_FOLDER = "crop"; //与FileProvider设置对应

    private static final String CROP_CACHE_FILE_NAME = "crop_cache_file.jpg";

    private static final String PIC_CACHE_FILE_NAME = "pick_cache_file.jpg";

    private static final String PIC_IMPRESS_CACHE_FILE_NAME = "pick_impress_cache_file.jpg";

    private CropParams cropParams;

    private ImgPickHandler handler;

    private boolean needCrop = true;

    private static class SingletonHolder {

        private static ImgPickHelper _instance = new ImgPickHelper();

    }

    public static ImgPickHelper getInstance() {
        return SingletonHolder._instance;
    }

    private ImgPickHelper() {
        cropParams = new CropParams();
    }

    public ImgPickHelper setParams(CropParams params) {
        this.cropParams = params;
        return this;
    }

    /**
     * 是否需要裁剪
     *
     * @param needCrop
     * @return
     */
    public ImgPickHelper needCrop(boolean needCrop) {
        this.needCrop = needCrop;
        return this;
    }

    public ImgPickHelper registeHandler(ImgPickHandler handler) {
        this.handler = handler;
        return this;
    }

    public ImgPickHelper unregistHandler() {
        this.handler = null;
        return this;
    }

    /**
     * 接管Activity的onAcrtivityResult
     *
     * @param activity
     * @param requestCode
     * @param resultCode
     * @param data
     */
    public void handleResult(Activity activity, int requestCode, int resultCode, Intent data) {
        if (handler == null) //没有handler，也就没有必要进行后续的工作了
            return;

        if (resultCode == Activity.RESULT_CANCELED) {
            handler.onCancel();
            return;
        }

        switch (requestCode) {
            case REQUEST_CAMERA:
                if (resultCode != Activity.RESULT_OK) {
                    handler.onFailed("");
                    return;
                }
                copyPhotoToTmpFile(activity, Uri.fromFile(createImageFile(activity, false)),createCompressImageFile(activity));
                if (needCrop)
                    goCrop(activity);
                else {
                    handler.onSuccess(Uri.fromFile(createCompressImageFile(activity)));
                }
                break;

            case REQUEST_Gallery:
                if (data == null) {
                    handler.onFailed("");
                    return;
                }
                /*if (data.getClipData() != null) {
                    int count = data.getClipData().getItemCount(); //evaluate the count before the for loop --- otherwise, the count is evaluated every loop.
                    for (int i = 0; i < count; i++) {

                        Uri imageUri = data.getClipData().getItemAt(i).getUri();


                        ContentResolver cr = getContext().getContentResolver();
                        try {
                            Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(imageUri));

                            String path = ImageUtils.getRealPathFromURI(getContext(),imageUri);

                        } catch (FileNotFoundException e) {
                            Log.e("Exception", e.getMessage(),e);
                        }

                    }
                }*/
                copyPhotoToTmpFile(activity, data.getData(), createImageFile(activity, false));

                if (needCrop)
                    goCrop(activity);
                else {
                    handler.onSuccess(Uri.fromFile(createImageFile(activity, false)));
                }
                break;

            case REQUEST_CROP:
                if (resultCode != Activity.RESULT_OK)
                    return;
                DebugLog.d("Photo cropped!");
                copyPhotoToTmpFile(activity, Uri.fromFile(createImageFile(activity, true)),createCompressImageFile(activity));

                handler.onSuccess(Uri.fromFile(createCompressImageFile(activity)));
                break;
        }
    }

    /**
     * 打开相机
     *
     * @param activity
     */
    public void goCamera(Activity activity) {
        try {


            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (Build.VERSION.SDK_INT >= 24) {

                Uri provider = FileProvider.getUriForFile(activity,
                        activity.getPackageName() + ".fileprovider",
                        createImageFile(activity, false));
                intent.putExtra(MediaStore.EXTRA_OUTPUT, provider);
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            } else {


                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(createImageFile(activity, false)));

            }
            activity.startActivityForResult(intent, ImgPickHelper.REQUEST_CAMERA);
        } catch (Exception e) {
            DebugLog.e("capture image exception - " + e.getMessage());
        }
    }

    /**
     * 打开相册
     *
     * @param activity
     */
    public void goGallery(Activity activity) {
        try {
            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            activity.startActivityForResult(intent, ImgPickHelper.REQUEST_Gallery);
        } catch (Exception e) {
            DebugLog.e("no action:android.intent.action.PICK", e);
        }
    }

    /**
     * 进行裁剪
     *
     * @param activity
     */
    private void goCrop(Activity activity) {
        try {
            //先干掉原来的，保证读取的时候拿到的是最新的
            File file = createImageFile(activity, true);

            if (file.exists()) {
                file.delete();
            }

            Intent intent = buildCropIntent(activity);

            activity.startActivityForResult(intent, REQUEST_CROP);
        } catch (Exception e) {
            DebugLog.e(e);
        }
    }

    /**
     * 创建一些临时文件
     *
     * @param isCrop
     * @return
     */
    private File createImageFile(Context context, boolean isCrop) {
        //用FileProvider提供的放在内部存储，更方便接口约定；处理后的照片不能保存在内部存储，所以放在外部
        File folder = isCrop ?
                new File(context.getExternalCacheDir(), CROP_CACHE_FOLDER)
                : new File(context.getCacheDir(), CROP_CACHE_FOLDER);
        if (!folder.exists())
            folder.mkdir();

        File file = new File(folder.getPath(), isCrop ? CROP_CACHE_FILE_NAME : PIC_CACHE_FILE_NAME);

        return file;
    }

    /**
     * 创建一些临时文件
     *
     * @return
     */
    private File createCompressImageFile(Context context) {
        //用FileProvider提供的放在内部存储，更方便接口约定；处理后的照片不能保存在内部存储，所以放在外部
        File folder = new File(context.getCacheDir(), CROP_CACHE_FOLDER);
        if (!folder.exists())
            folder.mkdir();

        File file = new File(folder.getPath(), PIC_IMPRESS_CACHE_FILE_NAME);

        return file;
    }

    /**
     * 将拍摄或选取的照片保存的临时文件里
     *
     * @param activity
     * @param sourUri
     */
    private void copyPhotoToTmpFile(Activity activity, Uri sourUri, File outFile) {
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(activity.getContentResolver().openInputStream(sourUri), null, options);
            int w = options.outWidth;
            int h = options.outHeight;
            float hh = 1024;//这里设置高度为800f
            //float ww = 720f;//这里设置宽度为480f
            int be = 1;//be=1表示不缩放
            if(w>h){//宽度大
                if(w>hh){//宽度超过了1280，需要压缩
                    int r=(int)(w/hh);
                    be=(int) Math.pow(2,(int)(Math.ceil(Math.log(r)/Math.log(2))));
                }
            }else{//高度大
                if(h>hh){//宽度超过了1280，需要压缩
                    int r=(int)(h/hh);
                    be=(int) Math.pow(2,(int)(Math.ceil(Math.log(r)/Math.log(2))));
                }
            }
            options.inSampleSize = be;//设置缩放比例
            options.inJustDecodeBounds = false;
            Bitmap photo = BitmapFactory.decodeStream(activity.getContentResolver().openInputStream(sourUri), null, options);

           /* BitmapFactory.Options outOptions = new BitmapFactory.Options();
            outOptions.inJustDecodeBounds = true;

            ContentResolver resolver = activity.getContentResolver();
            InputStream stream = resolver.openInputStream(sourUri);
            try {
                BitmapFactory.decodeStream(stream, null, outOptions);
            } finally {
                stream.close();
            }

            BitmapFactory.Options options = new BitmapFactory.Options();

            options.inPreferredConfig = Bitmap.Config.RGB_565;

            int widthScale = (int) Math.floor(outOptions.outWidth * 1f / PixelUtils.getScreenWidth());
            int heightScale = (int) Math.floor(outOptions.outHeight * 1f / PixelUtils.getScreenHeight());

            options.inSampleSize = widthScale > heightScale ? widthScale : heightScale;

            //使用ContentProvider通过URI获取原始图片
            stream = resolver.openInputStream(sourUri);
            Bitmap photo;
            try {
                photo = BitmapFactory.decodeStream(stream, null, options);
            } finally {
                stream.close();
            }*/

            if (photo != null) {
                String imagePath = ImageUtils.getRealPathFromURI(activity, sourUri);
                if(!TextUtils.isEmpty(imagePath)){
                    int degree = AsyncLoaderImage.readPictureDegree(imagePath);
                    if (degree != 0){
                        photo = AsyncLoaderImage.rotaingImageView(degree, photo);
                    }
                }

                BufferedOutputStream bos = new BufferedOutputStream(
                        new FileOutputStream(outFile));

                photo.compress(Bitmap.CompressFormat.JPEG, 80, bos);
                bos.flush();
                bos.close();
                photo.recycle();
            }


        } catch (Exception e) {
            DebugLog.e(e);
        }
    }

    /**
     * 创建裁剪所需的参数
     *
     * @param activity
     * @return
     */
    private Intent buildCropIntent(Activity activity) {
        Intent intent = new Intent("com.android.camera.action.CROP")
                .putExtra("crop", cropParams.crop)
                .putExtra("scale", cropParams.scale)
                .putExtra("aspectX", cropParams.aspectX)
                .putExtra("aspectY", cropParams.aspectY)
                //.putExtra("outputX", cropParams.outputX)
                //.putExtra("outputY", cropParams.outputY)
                .putExtra("return-data", cropParams.returnData)
                .putExtra("outputFormat", cropParams.outputFormat)
                .putExtra("noFaceDetection", cropParams.noFaceDetection)
                .putExtra("scaleUpIfNeeded", cropParams.scaleUpIfNeeded)
                .putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(createImageFile(activity, true)));

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            Uri provider = FileProvider.getUriForFile(activity,
                    activity.getPackageName() + ".fileprovider",
                    createImageFile(activity, false));

            intent.setDataAndType(provider, cropParams.type)
                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            intent.setDataAndType(Uri.fromFile(createImageFile(activity, false)), cropParams.type);
        }

        return intent;
    }

    /**
     * 清除掉临时文件
     *
     * @return
     */
    public boolean clearCachedCropFile(Context context) {

        File file = createImageFile(context, true).getParentFile();
        if (file.exists()) {
            boolean result = file.delete();
            if (result)
                DebugLog.d("Cached crop file cleared.");
            else
                DebugLog.e("Failed to clear cached crop file.");
            return result;
        } else {
            DebugLog.w("Trying to clear cached crop file but it does not exist.");
        }
        return false;
    }
}
